package com.idealighter.game.games.shuihu.common;

import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Table;

import com.idealighter.game.dictionary.dic.ShuihuIconDic;
import com.idealighter.game.dictionary.dic.ShuihuIconRewardDic;
import com.idealighter.game.dictionary.dic.ShuihuLineCoordDic;
import com.idealighter.game.dictionary.dic.ShuihuLineCoordDic.Coordinate;
import com.idealighter.game.dictionary.domain.ShuihuBonusNumCfgDomain;
import com.idealighter.game.games.shuihu.dto.LineRewardIcons;
import com.idealighter.game.games.shuihu.manager.ShuiHuMgr;
import com.idealighter.game.server.context.ApplicationContext;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * 水浒传奖励计算器 .
 * 
 * @date 2015年9月29日 下午3:07:54
 *
 */
public class RewardCalculator {

  // 水浒传id
  private static final int SHUI_HU_ZHUAN = 9;


  private RewardCalculator() {}

  /**
   * 根据图标和押注计算水浒传奖励.
   * 
   * @param icons 图标
   * @param line 压的线数
   * @param bet 每条线押注
   * @return 奖励
   */
  public static ShuiHuReward calculate(Table<Integer, Integer, Integer> icons,
      Map<Integer, ShuihuBonusNumCfgDomain> bonusNumCfgMap, int line, long bet) {
    // 赢的筹码
    long win = 0;
    // 小玛丽次数
    int bonus = 0;
    // 奖励类型(0:普通连线奖励 ,全盘奖励[1:铁斧,2:银枪,3:金刀,4:鲁智深,5:林冲,6:宋江,7:替天行道,8:忠义堂,9:水浒传,10:人物,11:武器]
    int type = 0;
    // 线路奖励图标列表
    List<LineRewardIcons> lineRewardIconsList = new ArrayList<>();

    ShuihuIconDic iconDic = ApplicationContext.getBean(ShuihuIconDic.class);
    ShuihuIconRewardDic iconRewardDic = ApplicationContext.getBean(ShuihuIconRewardDic.class);
    ShuihuLineCoordDic lineCoordDic = ApplicationContext.getBean(ShuihuLineCoordDic.class);
    ShuihuIconRewardDic shuihuIconRewardDic = ApplicationContext.getBean(ShuihuIconRewardDic.class);

    /*
     * 计算全盘奖励 . 和小玛丽次数
     */
    if (line == ShuiHuMgr.MAX_LINE) { // 压了9条线才有全盘奖
      // 奖励倍数
      int multiple = 0;
      // 图标set
      Set<Integer> iconsSet = new HashSet<>();
      // 图标类型set
      Set<Byte> iconsTypeSet = new HashSet<>();

      for (Integer icon : icons.values()) {
        iconsSet.add(icon);
        iconsTypeSet.add(iconDic.map().get(icon).getType());
      }

      /*
       * 图标全盘优先于人物全盘、武器全盘判断 .
       */
      if (iconsSet.size() == 1) {
        type = iconsSet.iterator().next();
        multiple = iconRewardDic.map().get(type).getAll();
        if (type == ShuiHuRewardType.ALL_REWARD_SHZ.getType()) { // 9 水浒传全盘,45次bonus
          bonus = bonusNumCfgMap.get(45).getBonusNum();
        }
      } else if (iconsTypeSet.size() == 1) {
        Byte iconsType = iconsTypeSet.iterator().next();
        if (iconsType == ShuiHuIconType.PERSON) { // 人物
          type = ShuiHuRewardType.ALL_REWARD_PERSON.getType(); // 10
          multiple = iconRewardDic.map().get(type).getAll();
        } else if (iconsType == ShuiHuIconType.WEAPON) { // 武器
          type = ShuiHuRewardType.ALL_REWARD_WEAPON.getType(); // 11
          multiple = iconRewardDic.map().get(type).getAll();
        }
      }

      // 所有线都翻倍
      win = line * bet * multiple;
    }

    /*
     * 没有全盘奖励，再计算普通线路奖励和小玛丽次数 .
     */
    if (win == 0) {
      for (int row = 1; row <= line; row++) {
        // 每条线的 图标坐标
        List<Coordinate> lineCoordinates = lineCoordDic.coordinates.get(row);
        // 每条线的 图标,可重复有序map
        LinkedListMultimap<Integer, Integer> lineIconsMap = LinkedListMultimap.create();

        for (Coordinate coordinate : lineCoordinates) {
          Integer icon = icons.get(coordinate.row, coordinate.column);
          lineIconsMap.put(icon, icon);
        }

        // 该线全是水浒传
        if (lineIconsMap.keySet().size() == 1 && lineIconsMap.keySet().contains(SHUI_HU_ZHUAN)) {
          LineRewardIcons destLineRewardIcons = new LineRewardIcons();
          destLineRewardIcons.setLine(row);
          destLineRewardIcons.setIcon(SHUI_HU_ZHUAN);
          Collections.addAll(destLineRewardIcons.getIndexs(), 0, 1, 2, 3, 4);
          lineRewardIconsList.add(destLineRewardIcons);

          bonus += bonusNumCfgMap.get(5).getBonusNum();
          int multiple = shuihuIconRewardDic.map().get(SHUI_HU_ZHUAN).getFiveLine();
          win += bet * multiple;
          continue;
        }

        // 该线有至少一个但不全是水浒传,需要将水浒传替换进行计算
        if (lineIconsMap.keySet().contains(SHUI_HU_ZHUAN)) {
          // 水浒传线路中奖图标信息
          LineRewardIcons destLineRewardIcons = new LineRewardIcons();
          destLineRewardIcons.setLine(row);
          bonus += calBonusNum(new ArrayList<>(lineIconsMap.values()), bonusNumCfgMap);

          // 水浒替换的最大倍数，eg:2,9,1,1,1
          int maxMultiple = 0;
          // 把水浒传替换进行计算
          for (Integer lineIcon : lineIconsMap.keySet()) {
            if (lineIcon != SHUI_HU_ZHUAN) {
              // 线路图标
              ArrayList<Integer> lineIcons = new ArrayList<>(lineIconsMap.values());
              // 线路中奖图标位置
              ArrayList<Integer> rewardIconIndexs = new ArrayList<>(5);
              Collections.replaceAll(lineIcons, SHUI_HU_ZHUAN, lineIcon);
              int multiple = calMultiple(lineIcons, rewardIconIndexs);
              if (multiple > maxMultiple) {
                maxMultiple = multiple;
                destLineRewardIcons.setIndexs(rewardIconIndexs);
                destLineRewardIcons.setIcon(lineIcons.get(rewardIconIndexs.get(0)));
              }
            }
          }

          if (maxMultiple > 0) {
            win += bet * maxMultiple;
            lineRewardIconsList.add(destLineRewardIcons);
            continue;
          }
        }

        // 该线没有水浒传
        if (!lineIconsMap.keySet().contains(SHUI_HU_ZHUAN)) {
          LineRewardIcons destLineRewardIcons = new LineRewardIcons();
          destLineRewardIcons.setLine(row);
          // 线路中奖图标位置
          ArrayList<Integer> rewardIconIndexs = new ArrayList<>(5);

          int multiple = calMultiple(new ArrayList<>(lineIconsMap.values()), rewardIconIndexs);
          if (multiple > 0) {
            win += bet * multiple;
            destLineRewardIcons.setIndexs(rewardIconIndexs);
            destLineRewardIcons.setIcon(lineIconsMap.values().get(rewardIconIndexs.get(0)));
            lineRewardIconsList.add(destLineRewardIcons);
          }
        }
      }
    }


    return new ShuiHuReward(win, bonus, type, lineRewardIconsList);
  }

  /**
   * 计算线路的5个图标的倍数,先算左边，没有再算右边.
   * 
   * @param lineIcons 线路的图标(没有水浒传)
   * @param rewardIconIndexs 中奖的图标
   * @return 赔率
   */
  private static int calMultiple(List<Integer> lineIcons, List<Integer> rewardIconIndexs) {
    int multiple = 0;
    // 左边第一个
    int leftFirst = lineIcons.get(0);
    // 左边连着的个数
    int leftNum = 1;
    for (int i = 1; i < lineIcons.size(); i++) {
      if (lineIcons.get(i) == leftFirst) {
        leftNum++;
      } else {
        break;
      }
    }

    multiple = getIconMultiple(leftFirst, leftNum);

    if (multiple > 0) {
      for (int i = 0; i < leftNum; i++) {
        rewardIconIndexs.add(i);
      }

      return multiple;
    } else {
      // 右边第一个
      int rightFirst = lineIcons.get(lineIcons.size() - 1);
      // 右边连着的个数
      int rightNum = 1;
      for (int i = lineIcons.size() - 2; i >= 0; i--) {
        if (lineIcons.get(i) == rightFirst) {
          rightNum++;
        } else {
          break;
        }
      }

      multiple = getIconMultiple(rightFirst, rightNum);
      if (multiple > 0) {
        for (int i = lineIcons.size() - 1; i >= lineIcons.size() - rightNum; i--) {
          rewardIconIndexs.add(i);
        }
      }

      return multiple;
    }

  }

  /**
   * 计算Bonus游戏次数, . 3/4/5个连着的才有.
   * 
   * @param lineIcons 连线
   * @return bonus数量
   */
  private static int calBonusNum(List<Integer> lineIcons,
      Map<Integer, ShuihuBonusNumCfgDomain> bonusNumCfgMap) {
    int bonusNum = 0;
    Integer leftFist = lineIcons.get(0);

    if (leftFist == SHUI_HU_ZHUAN) {
      // 左边连着的个数
      Integer leftNum = 1;
      for (int i = 1; i < lineIcons.size(); i++) {
        Integer icon = lineIcons.get(i);
        if (leftFist == icon) {
          leftNum++;
        } else {
          break;
        }
      }

      if (leftNum > 2) {
        bonusNum = bonusNumCfgMap.get(leftNum).getBonusNum();
        return bonusNum;
      }
    }

    Integer rightFist = lineIcons.get(lineIcons.size() - 1);

    if (rightFist == SHUI_HU_ZHUAN) {
      // 右边连着的个数
      Integer rightNum = 1;
      for (int i = lineIcons.size() - 2; i >= 0; i--) {
        Integer icon = lineIcons.get(i);
        if (rightFist == icon) {
          rightNum++;
        } else {
          break;
        }
      }

      if (rightNum > 2) {
        bonusNum = bonusNumCfgMap.get(rightNum).getBonusNum();;
        return bonusNum;
      }
    }



    return bonusNum;
  }

  /**
   * 获取图标的中奖倍数.
   * 
   * @param icon 图标
   * @param num 数量
   * @return 赔率
   */
  private static int getIconMultiple(int icon, int num) {
    int multiple = 0;
    ShuihuIconRewardDic shuihuIconRewardDic = ApplicationContext.getBean(ShuihuIconRewardDic.class);
    switch (num) { // 至少连着3个
      case 3:
        multiple = shuihuIconRewardDic.map().get(icon).getThreeLine();
        break;
      case 4:
        multiple = shuihuIconRewardDic.map().get(icon).getFourLine();
        break;
      case 5:
        multiple = shuihuIconRewardDic.map().get(icon).getFiveLine();
        break;
      default:
        break;
    }

    return multiple;
  }
}
